home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Snippets / PolyPumper 1.4.1 / PolyPumper.c < prev    next >
Encoding:
Text File  |  1995-12-15  |  13.4 KB  |  531 lines  |  [TEXT/CWIE]

  1. //• This is an itty bitty bytes™ production, no longer much resembling
  2. //• the derivation source (SplatMaster, by John Benton).
  3. //• It's free, and public domain.  Use it however you like and post
  4. //• it wherever you're allowed to.
  5.  
  6. //• Suggestions and requests welcome.
  7.  
  8. //• Enjoy!
  9.  
  10. //• kenlong@netcom.com
  11.  
  12. //• PolyPumper.c - for version 1.2.
  13.  
  14. #include <math.h>
  15.  
  16. //• --------------------------------------------------------------- •//
  17.  
  18. #define ourName "\pitty bitty bytes™"
  19. #define keys "\pHit 'K' for Keys."
  20. #define w 0xffff    //• Pseudo white, to save typing.
  21.  
  22. //• --------------------------------------------------------------- •//
  23.  
  24. Boolean singleUs = false;
  25. Boolean finishUs = false;
  26. Boolean framesUs = true;
  27. Boolean blacksUs = false;
  28. Boolean paintsUs = true;
  29. Boolean sticksUs = false;
  30. Boolean undivsUs = true;
  31. Boolean pausesUs = false;
  32. Boolean startsUs = true;
  33. Boolean weBeHued, weBeWaitin;
  34.  
  35. EventRecord theEvent;        
  36.  
  37. Point middle, originalPt, nextPt;
  38. PolyHandle Polly;    //• Grab a hold of Polly!
  39. Rect globWind, ourRect;
  40. PicHandle pict;
  41. Rect pictRect;
  42. WindowPtr pumpWindow;
  43. short lastSpot, radius, radius2, height;
  44. short divisions = 12;        //• Our point total.
  45. long ticks;
  46.  
  47. //• --------------------------------------------------------------- •//
  48.  
  49. void SetForeColor (short red, short green, short blue);
  50. void SetBackColor (short red, short green, short blue);
  51. unsigned short HighLowRandom (unsigned short min, unsigned short max);
  52. short RangeRandom (short range);
  53. void GetDivisions (void);
  54. void GetRadii (void);
  55. void DrawPolygons (void);
  56. void SetUpWindow (void);
  57. void InitManagers (short numMasters);
  58. Boolean CheckTheEquipment (void);
  59. void DoSplash (void);
  60. void SpoutOff (void);
  61. void main (void);
  62.  
  63. //• --------------------------------------------------------------- •//
  64.  
  65. void SetForeColor(short red, short green, short blue)
  66. {
  67.     RGBColor hue;
  68.  
  69.     hue.red = red;
  70.     hue.green = green;
  71.     hue.blue = blue;
  72.  
  73.     RGBForeColor (&hue);
  74. }
  75.  
  76. //• --------------------------------------------------------------- •//
  77.  
  78. void SetBackColor(short red, short green, short blue)
  79. {
  80.     RGBColor hue;
  81.  
  82.     hue.red = red;
  83.     hue.green = green;
  84.     hue.blue = blue;
  85.  
  86.     RGBBackColor (&hue);
  87. }
  88.  
  89. //• --------------------------------------------------------------- •//
  90.  
  91. unsigned short HighLowRandom (unsigned short min, unsigned short max)
  92. {
  93.     unsigned long ranger, tonto;
  94.     unsigned short rawResult;
  95.     
  96.     rawResult = Random ();
  97.     
  98.     if (rawResult < 0)
  99.         rawResult *= -1;
  100.     
  101.     ranger = max - min;
  102.     tonto = (rawResult * ranger) / 65535;
  103.     return (tonto + min);   
  104. }
  105.  
  106. //• --------------------------------------------------------------- •//
  107.  
  108. short RangeRandom (short range)
  109. {
  110.     long rawResult;
  111.  
  112.     rawResult = Random ();
  113.  
  114.     if (rawResult < 0)
  115.         rawResult *= - 1;
  116.     
  117.     return ((rawResult * range) / 32768);
  118. }
  119.  
  120. void GetDivisions ()
  121. {
  122.     //• Total points, inner plus outer.
  123.     //• Anywhere between 0 and 100.
  124.     //• I could have used "HighLowRandom (4, 100);" instead!  :^)
  125.     divisions = RangeRandom(100);
  126.     
  127.     //• Divisions must be even, so I rigged up a phoney "odd"
  128.     //• handler.  If divisions was 9, half of that is 4.5, rounded
  129.     //• up would be 5.
  130.     if (divisions != ceil((divisions / 2) * 2))
  131.         divisions++;
  132. }
  133.  
  134. void GetRadii ()
  135. {
  136.     //• This radius only gets positive values...
  137.     radius = RangeRandom(height);
  138.     
  139.     //• ...but this one gets positive and negative, so the
  140.     //• polygon points can lap, giving the "holey" effect.
  141.     radius2 = HighLowRandom (- height, height);
  142. }
  143.  
  144. //• --------------------------------------------------------------- •//
  145. //• The main action proc, where the magic takes place.
  146. void DrawPolygons ()
  147. {
  148.     short i;
  149.     double thetaStep, theta;
  150.     
  151.     //• Screen center is the start point.
  152.     middle.h = (qd.thePort->portRect.right  / 2);
  153.     middle.v = (qd.thePort->portRect.bottom / 2);
  154.  
  155.     //• The height of our overall draw area.
  156.     height = pumpWindow->portRect.bottom / 2 - 4;
  157.     
  158.     if (! undivsUs)
  159.         GetDivisions ();
  160.  
  161.     //• Less than 4 looks funky.  
  162.     if (divisions < 4)
  163.         divisions = 4;
  164.                     
  165.     if (! sticksUs)
  166.         GetRadii ();
  167.     
  168.     //• Some circle math thing...
  169.     thetaStep = (2 * 3.14159) / divisions;
  170.     theta = 0;
  171.     
  172.     //• Start recording polygon points.
  173.     Polly = OpenPoly ();
  174.     
  175.     //• SetPt handles .h and .v (cool).  Notice no need to
  176.     //• initialize "originalPt" before this?  The values are
  177.     //• calc'd off the already established "radius" value.
  178.     SetPt(&originalPt, radius * cos (theta),
  179.                           radius * sin (theta));
  180.     
  181.     //• Then we move to center, plus that "SetPt" value.
  182.     //• This is a horzontal offset from center, so our polygons
  183.     //• will be "laying on their sides" if half of divisons 
  184.     //• is odd.
  185.     MoveTo(middle.h + originalPt.h, middle.v + originalPt.v);
  186.  
  187.     //• Now that we have a start point, we go from there, around
  188.     //• the circle, for the number of divisions, which we made an 
  189.     //• even total.
  190.     for (i = 0; i < divisions; i++)
  191.     {
  192.         //• But, there are odd and even numbers in the sequence.
  193.         //• We want odd to be one radius and even to be the other.
  194.         //• So we jockey back and forth using the index as a guide.
  195.         if (i == ceil (i / 2) * 2)
  196.             SetPt(&nextPt, radius * cos (theta),
  197.                            radius * sin (theta));
  198.         else
  199.             SetPt(&nextPt, radius2 * cos (theta),
  200.                            radius2 * sin (theta));
  201.                            
  202.         //• Some other circle/math thing.  How far around?
  203.         theta += thetaStep;
  204.         
  205.         //• Still in our loop, we record where the poly point
  206.         //• is, off the center, to the point we just set.
  207.         LineTo(middle.h + nextPt.h, middle.v + nextPt.v);
  208.     }
  209.     //• Finally, we close the polygon with a line back to the
  210.     //• point we started at.
  211.     LineTo(middle.h + originalPt.h, middle.v + originalPt.v);
  212.     
  213.     //• Then stop recording.
  214.     ClosePoly ();
  215.     
  216.     //• Now set a color to paint the polygon with, and paint it
  217.     //• *IF* we're painting.
  218.     if (paintsUs == true)
  219.     {
  220.         SetForeColor (Random (), Random (), Random ());
  221.         PaintPoly (Polly);
  222.     }
  223.     
  224.     //• Then set the forecolor to black for the frame 
  225.     //• *IF* we're framing.
  226.     if (framesUs == true)
  227.     {
  228.         SetForeColor (0, 0, 0);
  229.         FramePoly (Polly);
  230.     }
  231.     
  232.     //• Now dump all the memory this took, 
  233.     //• since the pixels are now ON the screen!
  234.     KillPoly (Polly);
  235. }
  236.  
  237. //• --------------------------------------------------------------- •//
  238. //• "Cheapo" window, but it works!  Set to srceen edges.
  239. void SetUpWindow (void)
  240. {
  241.     HideMenuBar ();            //• Do this while we're here.
  242.     pumpWindow = NewCWindow (0L, &qd.screenBits.bounds, "\p", true, 
  243.                             plainDBox, (WindowPtr) -1L, true, 0);
  244.     SetPort (pumpWindow);
  245.     HideCursor ();            //• Swat the fly, too.
  246.     DoSplash ();            //• Do some heavy bragging.
  247. }
  248.  
  249. //• --------------------------------------------------------------- •//
  250.  
  251. void InitManagers (short numMasters)
  252. {
  253.     short i;            
  254.                                 //• The manager's names:
  255.     InitGraf (&qd.thePort);        //• Quick Draw McGraw.
  256.     InitFonts ();                //• Alfonso
  257.     InitWindows ();                //• Windex.
  258.     TEInit ();                    //• Te he he.
  259.     InitDialogs (((void *) 0));    //• Paul Bunion (lumberjack).
  260.     
  261.     for (i = 0; i < 5; i++)
  262.     {
  263.         MoreMasters ();            
  264.     }
  265.     FlushEvents (everyEvent, 0);
  266.     InitCursor ();                //• Watch your language!
  267. }
  268.  
  269. //• --------------------------------------------------------------- •//
  270. //• A hold-over from where I got it (SplatMaster).
  271. //• Mainly check for color is what we want.
  272. Boolean CheckTheEquipment (void)
  273. {
  274.     #define versRequested         1        //• This is a 68000
  275.     #define The_Wait_Trap     0x60
  276.     #define Unimpl_Pimple     0x9f
  277.  
  278.     OSErr err;
  279.     SysEnvRec theWorld;                //• Wrecking the world?
  280.     Boolean runability = false;        //• Got legs?
  281.  
  282.     weBeHued = false;
  283.  
  284.     err = SysEnvirons(versRequested, &theWorld);
  285.  
  286.     //• Fi this is a 68000 Mac, we skip to _L99 with runability false.
  287.     if (err != noErr)
  288.         goto _L99;        //• The dreaded "goto."  Actually useful.
  289.  
  290.     //• If there was no error in the "noErr", we read this.
  291.     //• _L99, runability still false, on a MacSE.
  292.     if (theWorld.machineType <= 3)
  293.         goto _L99;
  294.  
  295.     //• If the machineType was okay, we read this.
  296.     if (theWorld.hasColorQD)
  297.         weBeHued = true;            //• Huey To-us and the News!
  298.  
  299.     //• If we made it this far...
  300.     runability = true;                //• Doesn't apply to Ross Perot.
  301.     
  302.     //• Why do this?  We're using "GetNextEvent!"  Leftovers.
  303.     weBeWaitin = (NGetTrapAddress(The_Wait_Trap, ToolTrap) !=
  304.                   NGetTrapAddress(Unimpl_Pimple, ToolTrap));
  305.  
  306. _L99:
  307.     if (runability)
  308.         return true;
  309. }
  310.  
  311. //• --------------------------------------------------------------- •//
  312. void DoSplash ()        //• Much ado over nothing!
  313. {
  314.     short pR, pB, sR, sB, L, T, R, B;    //• Some stuff to save typing
  315.                                         //• in our SetRect call :^)
  316.     pict = GetPicture (128);
  317.  
  318.     if (pict != 0L)
  319.     {
  320.         pR = (**pict).picFrame.right;
  321.         pB = (**pict).picFrame.bottom;
  322.         sR = pumpWindow->portRect.right; 
  323.         sB = pumpWindow->portRect.bottom;
  324.         L = sR / 2 - pR / 2;
  325.         T = sB / 2 - pB / 2;
  326.         R = L + pR;
  327.         B = T + pB;
  328.         SetRect (&pictRect, L, T, R, B);
  329.         DrawPicture (pict, &pictRect);
  330.         ReleaseResource ((Handle) pict);
  331.     }
  332.     while (! Button ())        //• If we ain't clickin'...
  333.         ;                    //• we keeps on stickin'!
  334.     
  335.     EraseRect (&pictRect);
  336.     if (startsUs)
  337.     {
  338.         DoInstructions ();
  339.         startsUs = false;
  340.     }
  341.     SpoutOff ();            //• Put this up, initially.
  342. }
  343.  
  344. //• --------------------------------------------------------------- •//
  345. DoInstructions ()
  346. {
  347.     pict = GetPicture (129);
  348.      EraseRect (&pumpWindow->portRect);
  349.      
  350.     if (pict != 0L)
  351.     {
  352.          DrawPicture (pict, &pictRect);
  353.         ReleaseResource ((Handle) pict);
  354.     }
  355.     while (! Button ())        //• If we ain't clickin'...
  356.         ;                    //• we keeps on stickin'!
  357.     EraseRect (&pictRect);
  358.     SpoutOff ();
  359. }    
  360.     
  361. //     Str255 s00 = "\pSINGLE KEY CONTROLS:",
  362. //            s01 = "\p+........Increase divisions by two.",
  363. //            s02 = "\p-........Decrease divisions by two.",
  364. //            s03 = "\p*........Pause or not.",
  365. //            s04 = "\pB........White or black background.",
  366. //            s05 = "\pD........Divisons random or not.",
  367. //            s06 = "\pE........Erase window once.",
  368. //            s07 = "\pF........Frame polygon or not.",
  369. //            s08 = "\pI........Show these instructions again.",
  370. //            s09 = "\pP........Paint polygon or not.",
  371. //            s10 = "\pR........Radii random or not.",
  372. //            s11 = "\pS........Erase window after 1 second delay, or not.",
  373. //            s12 = "\pQ........Quit.",
  374. //            s13 = "\pCLICK TO EXIT INSTRUCTIONS";
  375. //     
  376. //     //• Wipe the slate and put up instructions.
  377. //     EraseRect (&pumpWindow->portRect);
  378. //     Delay (20L, &ticks);
  379. //     MoveTo (20,  40); DrawString (s00);
  380. //     MoveTo (20,  60); DrawString (s01);
  381. //     MoveTo (20,  80); DrawString (s02);
  382. //     MoveTo (20, 100); DrawString (s03);
  383. //     MoveTo (20, 120); DrawString (s04);
  384. //     MoveTo (20, 140); DrawString (s05);
  385. //     MoveTo (20, 160); DrawString (s06);
  386. //     MoveTo (20, 180); DrawString (s07);
  387. //     MoveTo (20, 200); DrawString (s08);
  388. //     MoveTo (20, 220); DrawString (s09);
  389. //     MoveTo (20, 240); DrawString (s10);
  390. //     MoveTo (20, 260); DrawString (s11);
  391. //     MoveTo (20, 280); DrawString (s12);
  392. //     MoveTo (20, 320); DrawString (s13);
  393. //     while (! Button ())
  394. //         ;
  395. //     //• Wipe the slate and on with the show!
  396. //     EraseRect (&pumpWindow->portRect);
  397. //}
  398.  
  399. //• --------------------------------------------------------------- •//
  400. //• Brag a little, and let user know how to get out, etc.
  401. void SpoutOff ()
  402. {
  403.     SetForeColor (w / 2, w / 2, w / 2);
  404.     
  405.     MoveTo (5, pumpWindow->portRect.bottom - 5);
  406.     DrawString (keys);
  407.     MoveTo (pumpWindow->portRect.right - StringWidth (ourName) - 5, 
  408.             pumpWindow->portRect.bottom - 5);
  409.     DrawString (ourName);
  410. }        
  411.         
  412. //• --------------------------------------------------------------- •//
  413.  
  414. void main ()
  415. {
  416.     short chCode;
  417.     char theKey;
  418.     unsigned long myRand = qd.randSeed;
  419.     
  420.     GetDateTime (&myRand);
  421.     
  422.     InitManagers (5);
  423.     if (CheckTheEquipment())     //• Find out about our environment.
  424.     {
  425.         SetUpWindow ();
  426.         do
  427.         {
  428.             if (GetNextEvent(everyEvent, &theEvent))
  429.                 switch (theEvent.what)
  430.                 {
  431.                     case keyDown:
  432.                         chCode = (theEvent.message & charCodeMask);
  433.                         //• These key hits are self explanatory.
  434.                         switch (chCode)
  435.                         {
  436.                             case 'b':
  437.                                 if (blacksUs == false)
  438.                                 {
  439.                                     SetBackColor (w, w, w);
  440.                                     EraseRect (&pumpWindow->portRect);
  441.                                 }
  442.                                 else
  443.                                 {
  444.                                     SetBackColor (0, 0, 0);
  445.                                     EraseRect (&pumpWindow->portRect);
  446.                                 }
  447.                                 SpoutOff ();
  448.                                 blacksUs = ! blacksUs;
  449.                             break;
  450.                             
  451.                             case 'd':
  452.                                 undivsUs = ! undivsUs;
  453.                             break;
  454.                             
  455.                             case 'a':            //• Wipe.
  456.                                 EraseRect (&pumpWindow->portRect);
  457.                                 DoSplash ();    //• Put this back.
  458.                             break;
  459.                             
  460.                             case 'c':            //• Wipe.
  461.                                 EraseRect (&pumpWindow->portRect);
  462.                                 SpoutOff ();    //• Put this back.
  463.                             break;
  464.                             
  465.                             case 'f':
  466.                                 framesUs = ! framesUs;
  467.                             break;
  468.  
  469.                             case 'k':
  470.                                 DoInstructions ();
  471.                                 //• Flush in case user hit 'i' again.
  472.                                 FlushEvents (everyEvent, 0);
  473.                                 SpoutOff ();
  474.                             break;
  475.  
  476.                             case 'p':
  477.                                 paintsUs = ! paintsUs;
  478.                             break;
  479.                             
  480.                             case 'q':
  481.                                 finishUs = true;
  482.                             break;
  483.                             
  484.                             case 'r':
  485.                                 sticksUs = ! sticksUs;
  486.                             break;
  487.                             
  488.                             case 's':
  489.                                 singleUs = ! singleUs;
  490.                             break;
  491.  
  492.                             case '+':
  493.                                 divisions += 2;
  494.                             break;
  495.  
  496.                             case '-':
  497.                                 divisions -= 2;
  498.                             break;
  499.  
  500.                             case '*':
  501.                                 pausesUs = ! pausesUs;
  502.                             break;
  503.                         }
  504.                     break;
  505.                     
  506.                     //• It does this every time, unless something
  507.                     //• changes.
  508.                     default:
  509.                         //• Do this *IF* single is true and
  510.                         //• pausing is false.
  511.                         if ((singleUs) && (! pausesUs))
  512.                         {
  513.                             DrawPolygons ();
  514.                             Delay (59L, &ticks);
  515.                             EraseRect (&pumpWindow->portRect);
  516.                             SpoutOff ();
  517.                         }
  518.                         //• Otherwise just draw, unless paused.
  519.                         if ((! singleUs) && (! pausesUs))
  520.                             DrawPolygons ();
  521.                     break;
  522.                 }
  523.         }while (! finishUs);    //• 'q' key sets us free.
  524.     }
  525.     ShowMenuBar ();        //• This would probably happen anyway, but...
  526.     InitCursor ();
  527. }
  528.  
  529. //• --------------------------------------------------------------- •//
  530.  
  531. //• We're outta here!